package com.huawei.mylibrary.view;

import com.huawei.mylibrary.ResourceTable;
import com.huawei.mylibrary.callback.FailAuthCounterCallback;
import com.huawei.mylibrary.callback.FingerprintCallback;
import com.huawei.mylibrary.callback.FingerprintSecureCallback;
import com.huawei.mylibrary.utils.CipherHelper;
import ohos.agp.colors.RgbColor;
import ohos.agp.components.*;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.components.element.VectorElement;
import ohos.app.Context;
import ohos.biometrics.authentication.BiometricAuthentication;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.global.configuration.DeviceCapability;
import ohos.global.resource.solidxml.TypedAttribute;

public class Fingerprint extends DependentLayout {
    private final static String TAG = "FingerprintView";
    private Component fingerprintImageView;
    private Component circleView;


    private FingerprintCallback fingerprintCallback;
    private FingerprintSecureCallback fingerprintSecureCallback;
    private FailAuthCounterCallback counterCallback;
    private CipherHelper cipherHelper;
    private BiometricAuthentication cancellationSignal;

//    private FingerprintManager fingerprintManager;
//    private FingerprintManager.CryptoObject cryptoObject;

    private int fingerprintScanning, fingerprintSuccess, fingerprintError;
    private int circleScanning, circleSuccess, circleError;

    private EventHandler handler;


    private int limit, tryCounter;
    private int delayAfterError;
    private int size;

    public final static int DEFAULT_DELAY_AFTER_ERROR = 1200;
    public final static int DEFAULT_CIRCLE_SIZE = 50;
    public final static int DEFAULT_FINGERPRINT_SIZE = 30;
    public final static float SCALE = (float) DEFAULT_FINGERPRINT_SIZE / DEFAULT_CIRCLE_SIZE;

    public Fingerprint(Context context) {
        super(context);
    }

    public Fingerprint(Context context, AttrSet attrs) {
        super(context, attrs);
        initAttributes(context, attrs, 0, 0);
        initView(context);
    }

    public Fingerprint(Context context, AttrSet attrs, int defStyleAttr) {
        // TODO 要求string
//        super(context, attrs, defStyleAttr);
        super(context, attrs, String.valueOf(defStyleAttr));
        initAttributes(context, attrs, defStyleAttr, 0);
        initView(context);
    }

//  TODO 缺少构造
//    public Fingerprint(Context context, AttrSet attrs, int defStyleAttr, int defStyleRes) {
//        super(context, attrs, defStyleAttr, defStyleRes);
//        initAttributes(context, attrs, defStyleAttr, defStyleRes);
//        initView(context);
//    }

    //TODO
//    @SuppressLint("ResourceType")
    private void initAttributes(Context context, AttrSet attrs, int defStyleAttr, int defStyleRes) {

//        TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.Fingerprint, defStyleAttr, defStyleRes);
//        try {
//            fingerprintScanning = a.getResourceId(R.styleable.Fingerprint_fingerprintScanningColor, R.color.fingerprint_scanning);
//            fingerprintSuccess = a.getResourceId(R.styleable.Fingerprint_fingerprintSuccessColor, R.color.fingerprint_success);
//            fingerprintError = a.getResourceId(R.styleable.Fingerprint_fingerprintErrorColor, R.color.fingerprint_error);
//
//            circleScanning = a.getResourceId(R.styleable.Fingerprint_circleScanningColor, R.color.circle_scanning);
//            circleSuccess = a.getResourceId(R.styleable.Fingerprint_circleSuccessColor, R.color.circle_success);
//            circleError = a.getResourceId(R.styleable.Fingerprint_circleErrorColor, R.color.circle_error);
//        } finally {
//            a.recycle();
//        }
//
//        int[] systemAttrs = {android.R.attr.layout_width, android.R.attr.layout_height};
//        TypedArray ta = context.obtainStyledAttributes(attrs, systemAttrs);
//        try {
//            int width = ta.getLayoutDimension(0, ViewGroup.LayoutParams.WRAP_CONTENT);
//            int height = ta.getLayoutDimension(1, ViewGroup.LayoutParams.WRAP_CONTENT);
//            if(width==-2 || height==-2) {
//                size = dipToPixels(DEFAULT_CIRCLE_SIZE);
//            } else{
//                size = width;
//            }
//        } finally {
//            ta.recycle();
//        }
    }


    private void initView(Context context) {
        //TODO
//        this.fingerprintManager = (FingerprintManager) context.getSystemService(Context.FINGERPRINT_SERVICE);
        this.cipherHelper = null;
        this.handler = new EventHandler(EventRunner.getMainEventRunner());
        this.fingerprintCallback = null;
        this.fingerprintSecureCallback = null;
        this.counterCallback = null;
//        this.cryptoObject = null;
        this.tryCounter = 0;
        this.delayAfterError = DEFAULT_DELAY_AFTER_ERROR;

        int fingerprintSize = (int) (size * SCALE);
        int circleSize = size;

        fingerprintImageView = new Image(context);
        fingerprintImageView.setLayoutConfig(new LayoutConfig(fingerprintSize, fingerprintSize));
        VectorElement vectorElement = new VectorElement(context, ResourceTable.Graphic_fingerprint);
        fingerprintImageView.setBackground(vectorElement);

        ((DependentLayout.LayoutConfig) fingerprintImageView.getLayoutConfig()).addRule(LayoutConfig.CENTER_IN_PARENT, LayoutConfig.TRUE);
        circleView = new Component(context);
        circleView.setLayoutConfig(new DependentLayout.LayoutConfig(circleSize, circleSize));
        ShapeElement vectorElement2 = new ShapeElement(context, ResourceTable.Graphic_circle);
        circleView.setBackground(vectorElement2);
        ((DependentLayout.LayoutConfig) circleView.getLayoutConfig()).addRule(LayoutConfig.CENTER_IN_PARENT, LayoutConfig.TRUE);

        setLayoutConfig(new DependentLayout.LayoutConfig(LayoutConfig.MATCH_CONTENT, LayoutConfig.MATCH_CONTENT));

        addComponent(circleView);
        addComponent(fingerprintImageView);
        setStatus(ResourceTable.Graphic_fingerprint, fingerprintScanning, circleScanning);
    }

// TODO 缺少dipValue
    private int dipToPixels(int dipValue) {
//   TODO 获取亮度 DeviceCapability构造方法不详
//        DisplayMetrics metrics = getResources().getDisplayMetrics();
//        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dipValue, metrics);
        return (int) TypedAttribute.computeTranslateRatio(new DeviceCapability());
    }

    private void setStatus(int drawableId, int drawableColorId, int circleColorId) {
        Context context = getContext();
        VectorElement element = new VectorElement(context, drawableId);
        fingerprintImageView.setBackground(element);
        //TODO
//        fingerprintImageView.setBackgroundTintList(ColorStateList.valueOf(context.getColor(drawableColorId)));
//        circleView.setBackgroundTintList(ColorStateList.valueOf(context.getColor(circleColorId)));
    }

    private Runnable returnToScanning = new Runnable() {
        @Override
        public void run() {
            setStatus(ResourceTable.Graphic_fingerprint, fingerprintScanning, circleScanning);
        }
    };

    private Runnable checkForLimit = new Runnable() {
        @Override
        public void run() {
            if (counterCallback != null && ++tryCounter == limit) {
                counterCallback.onTryLimitReached(Fingerprint.this);
            }
        }
    };

    public Fingerprint callback(FingerprintCallback fingerprintCallback) {
        this.fingerprintCallback = fingerprintCallback;
        return this;
    }

    /**
     * Set fingerprint secure callback.
     *
     * @param fingerprintSecureCallback secure callback
     * @param KEY_NAME                  key that will be used for the cipher
     * @return the Fingerprint object itself
     */
    public Fingerprint callback(FingerprintSecureCallback fingerprintSecureCallback, String KEY_NAME) {
        this.fingerprintSecureCallback = fingerprintSecureCallback;
        this.cipherHelper = new CipherHelper(KEY_NAME);
        return this;
    }

    public Fingerprint circleScanningColor(int circleScanning) {
//        this.fingerprintImageView.setBackgroundTintList(ColorStateList.valueOf(getContext().getColor(fingerprintScanning)));

        this.circleScanning = circleScanning;
        ShapeElement element = new ShapeElement();
        element.setRgbColor(new RgbColor(255, 0, 0));
        this.circleView.setBackground(element);
        return this;
    }

    public Fingerprint fingerprintScanningColor(int fingerprintScanning) {
//        this.fingerprintImageView.setBackgroundTintList(ColorStateList.valueOf(getContext().getColor(fingerprintScanning)));

        this.fingerprintScanning = fingerprintScanning;
        ShapeElement element = new ShapeElement();
        element.setRgbColor(new RgbColor(0, 0, 255));
        this.fingerprintImageView.setBackground(element);
        return this;
    }


    /**
     * Set the fingerprint icon color in success state.
     *
     * @param fingerprintSuccess color id
     * @return the Fingerprint object itself
     */
    public Fingerprint fingerprintSuccessColor(int fingerprintSuccess) {
        this.fingerprintSuccess = fingerprintSuccess;
//        this.fingerprintImageView.setBackgroundTintList(ColorStateList.valueOf(getContext().getColor(fingerprintSuccess)));
        ShapeElement element = new ShapeElement();
        element.setRgbColor(new RgbColor(0, 255, 0));
        this.fingerprintImageView.setBackground(element);
        return this;
    }

    /**
     * Set the fingerprint icon color in error state.
     *
     * @param fingerprintError color id
     * @return the Fingerprint object itself
     */
    public Fingerprint fingerprintErrorColor(int fingerprintError) {
        this.fingerprintError = fingerprintError;
//        this.fingerprintImageView.setBackgroundTintList(ColorStateList.valueOf(getContext().getColor(fingerprintError)));
        ShapeElement element = new ShapeElement();
        element.setRgbColor(new RgbColor(0, 0, 255));
        this.fingerprintImageView.setBackground(element);
        return this;
    }

    /**
     * Set the fingerprint circular background color in success state.
     *
     * @param circleSuccess color id
     * @return the Fingerprint object itself
     */
    public Fingerprint circleSuccessColor(int circleSuccess) {
        this.circleSuccess = circleSuccess;
//        this.circleView.setBackgroundTintList(ColorStateList.valueOf(getContext().getColor(circleSuccess)));
        ShapeElement element = new ShapeElement();
        element.setRgbColor(new RgbColor(0, 0, 255));
        this.circleView.setBackground(element);
        return this;
    }


    /**
     * Set the fingerprint circular background color in error state.
     *
     * @param circleError color id
     * @return the Fingerprint object itself
     */
    public Fingerprint circleErrorColor(int circleError) {
        this.circleError = circleError;
//        this.circleView.setBackgroundTintList(ColorStateList.valueOf(getContext().getColor(circleError)));
        ShapeElement element = new ShapeElement();
        element.setRgbColor(new RgbColor(255, 0, 0));
        this.circleView.setBackground(element);
        return this;
    }

    /**
     * Set a failing authentication limit. Android will block automatically the fingerprint scanner when 5 attempts will have failed.
     *
     * @param limit           the number of fails accepted
     * @param counterCallback a callback triggered when limit is reached
     * @return the Fingerprint object itself
     */
    public Fingerprint tryLimit(int limit, FailAuthCounterCallback counterCallback) {
        this.limit = limit;
        this.counterCallback = counterCallback;
        return this;
    }


    /**
     * Set delay before scanning again after a failed authentication.
     *
     * @param delayAfterError the delay in milliseconds
     * @return the Fingerprint object itself
     */
    public Fingerprint delayAfterError(int delayAfterError) {
        this.delayAfterError = delayAfterError;
        return this;
    }


    /**
     * Check if fingerprint authentication is supported by the device and if a fingerprint is enrolled in the device.
     *
     * @param context an activity context
     * @return a boolean value
     */
    public static boolean isAvailable(Context context) {
        // TODO FingerprintManager
//        FingerprintManager fingerprintManager = (FingerprintManager) context.getSystemService(Context.FINGERPRINT_SERVICE);
//        if(fingerprintManager!=null){
//            return (fingerprintManager.isHardwareDetected() && fingerprintManager.hasEnrolledFingerprints());
//        }
//        return false;
        return true;
    }

    //TODO
    public void authenticate() {
        if (fingerprintCallback != null) {
//            if(cryptoObject!=null){
//                throw new RuntimeException("If you specify a CryptoObject you have to use FingerprintCallback");
//            }

        }


    }

    /**
     * cancel fingerprint scan
     */
    public void cancel() {
        cancellationSignal.cancelAuthenticationAction();
        returnToScanning.run();
    }

}
